home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr25 / rxcalc.zip / REXXCAL1.C < prev    next >
Text File  |  1993-03-01  |  16KB  |  340 lines

  1. /*********************************************************************/
  2. /*                                                                   */
  3. /* REXXCALC - A simple PM based pocket calculator                    */
  4. /*                                                                   */
  5. /*********************************************************************/
  6.  
  7. /* Standard C libraries */
  8.  
  9. #include <stdlib.h>
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <math.h>
  13.  
  14.  /* Include specific parts of the OS/2 and presentation manager      */
  15.  /* definitions                                                      */
  16.  
  17. #define INCL_WIN
  18. #include <os2.h>
  19. #define INCL_RXFUNC
  20. #include <rexxsaa.h>
  21.  
  22. /* Include the constants file created by the Dialog Box Editor.      */
  23. /* This include file defines symbols for all elements of the         */
  24. /* calculator dialog.                                                */
  25.  
  26. #include <rexxcal1.h>
  27.  
  28. /* Declare prototypes for all subroutines.                           */
  29.  
  30. INT main(VOID);                        /* Main PM calculator program */
  31.  
  32.                                        /* Calculator dialog          */
  33. MRESULT EXPENTRY Calculator(HWND, ULONG, MPARAM, MPARAM);
  34. VOID    ProcessArithmetic(LONG);       /* Arithmetic processor       */
  35. VOID    AddDigit(INT);                 /* add digit to display       */
  36. INT     GetDisplay(VOID);              /* get display value          */
  37. VOID    SetDisplay(LONG);              /* set new display            */
  38.  
  39. /* Define some constants for the calculator dialog                   */
  40.  
  41. #define DISPLAY_WIDTH    20            /* width of display area      */
  42. #define MAX_DIGITS        8            /* maximum digits in display  */
  43.  
  44. /* Global data used for the dialog                                   */
  45.  
  46.  HAB    hab;                           /* Anchor block handle        */
  47.  HWND   hwndCalc;                      /* Handle for calculator      */
  48.                                        /*   dialog (created using    */
  49.                                        /*   the dialog editor)       */
  50.  
  51. /* Global data used for the calculator                               */
  52.  
  53.  UCHAR  display[DISPLAY_WIDTH];        /* Displayed number string    */
  54.  LONG   accumulator;                   /* current register value     */
  55.  LONG   operand;                       /* converted operand number   */
  56.  INT    oldaction;                     /* pending key action         */
  57.  INT    digits;                        /* number of digits in display*/
  58.  
  59. /*********************************************************************/
  60. /* main() - the main calculator program entry point                  */
  61. /*********************************************************************/
  62.  
  63. INT main()
  64. {
  65.   HMQ   hmq;                           /* Message queue handle       */
  66.   QMSG  qmsg;                          /* Receive PM queue message   */
  67.  
  68.                                        /* startup PM usage           */
  69.   hab = WinInitialize(0);              /* Get the anchor block handle*/
  70.   hmq = WinCreateMsgQueue(hab, 0);     /* Create the message queue   */
  71.                                        /* register our window class  */
  72.   WinRegisterClass(hab, "RexxCalc", Calculator, 0l, 0);
  73.  
  74.   /* Load the calculator dialog.  The dialog definitions are in      */
  75.   /* rexxcalc.rc                                                     */
  76.  
  77.   hwndCalc = WinLoadDlg(HWND_DESKTOP, HWND_DESKTOP,
  78.                         NULL,
  79.                         0,     
  80.                         REXXCALC,      /* Dialog ID                  */
  81.                         NULL);
  82.  
  83.   WinSendMsg(hwndCalc, WM_SETICON,     /* Set program icon           */
  84.       (MPARAM)WinLoadPointer(HWND_DESKTOP, 0, REXXCALC), 0);
  85.  
  86.                                        /* set the window focus       */
  87.   WinSetFocus(HWND_DESKTOP,
  88.       WinWindowFromID(hwndCalc, FID_CLIENT));
  89.  
  90.   /* Process the standard Presentation Manager message loop until    */
  91.   /* we are told to terminate                                        */
  92.  
  93.                                        /* While more messages        */
  94.   while (WinGetMsg(hab, &qmsg, 0, 0, 0))
  95.      WinDispatchMsg(hab, &qmsg);       /* dispatch application       */
  96.                                        /*   message handler          */
  97.  
  98.  
  99.   /* The close option has been selected so we need to clean up       */
  100.   /* our context.                                                    */
  101.  
  102.   WinDestroyWindow(hwndCalc);          /* Destroy the dialog window  */
  103.   WinDestroyMsgQueue(hmq);             /* Destroy the message queue  */
  104.   WinTerminate(hab);                   /* Terminate PM usage         */
  105.   return (0);                          /* Indicate successful        */
  106.                                        /*   completion               */
  107. }
  108.  
  109. /*********************************************************************/
  110. /*                                                                   */
  111. /* Calculator() - the PM WinProc for handling the calculator dialog. */
  112. /* The dialog itself has been created using the dialog box editor.   */
  113. /* This seperates the actual form of the calculator from the program */
  114. /* source.                                                           */
  115. /*                                                                   */
  116. /*********************************************************************/
  117.  
  118. MRESULT EXPENTRY Calculator(
  119.   HWND    hwnd,                        /* window handle              */
  120.   ULONG   msg,                         /* dispatched message id      */
  121.   MPARAM  mp1,                         /* first message parameter    */
  122.   MPARAM  mp2 )                        /* second message parameter   */
  123. {
  124.   ULONG   action;                      /* Action to process          */
  125.  
  126.    switch (msg) {                      /* switch based on the message*/
  127.                                        /* received                   */
  128.  
  129.       /* The initialization message has been received.  We do some   */
  130.       /* additional fixup of the dialog to make it look a little     */
  131.       /* nicer.                                                      */
  132.  
  133.       case WM_INITDLG:
  134.  
  135.          accumulator = 0;              /* clear the accumulator      */
  136.          oldaction = 0;                /* no pending operations      */
  137.          operand = 0;                  /* no operand                 */
  138.          digits = 0;                   /* no digits in display       */
  139.          SetDisplay(accumulator);      /* set initial display value  */
  140.                                        /* update the calculator      */
  141.                                        /* display                    */
  142.          WinSetWindowText(WinWindowFromID(hwnd, DISPLAY), display);
  143.          return FALSE;                 /* initialization complete    */
  144.  
  145.       /* We are going away, time to post a quit message to the       */
  146.       /* message loop.                                               */
  147.  
  148.       case WM_CLOSE:
  149.                                        /* Standard Close processing  */
  150.          WinPostMsg(hwnd, WM_QUIT, 0L, 0L);
  151.          return FALSE;                 /* Exit now                   */
  152.  
  153.       /* We've received a WM_COMMAND message.  WM_COMMAND messages   */
  154.       /* are generated by "pressing" buttons on the calculator.  The */
  155.       /* additional parameters in the received message identify the  */
  156.       /* button that was pressed                                     */
  157.  
  158.       case WM_COMMAND:
  159.  
  160.          action = SHORT1FROMMP(mp1);   /* Extract message sub-type   */
  161.  
  162.          switch (action) {
  163.  
  164.             /* The following buttons will be processed by the actual */
  165.             /* calculator routine                                    */
  166.  
  167.             case BUTTON_CLEAR:         /* Clear key                  */
  168.  
  169.               accumulator = 0;         /* clear the accumulator      */
  170.               oldaction = 0;           /* and any pending operations */
  171.               SetDisplay(accumulator); /* set the new display value  */
  172.                                        /* update the calculator      */
  173.                                        /* display                    */
  174.               WinSetWindowText(WinWindowFromID(hwnd, DISPLAY),
  175.                   display);
  176.               return FALSE;            /* All done                   */
  177.  
  178.             case BUTTON_0:             /* Numeric keys               */
  179.             case BUTTON_1:
  180.             case BUTTON_2:
  181.             case BUTTON_3:
  182.             case BUTTON_4:
  183.             case BUTTON_5:
  184.             case BUTTON_6:
  185.             case BUTTON_7:
  186.             case BUTTON_8:
  187.             case BUTTON_9:
  188.  
  189.                                        /* Add a digit to display     */
  190.               AddDigit(action - BUTTON_0);
  191.                                        /* update the accumulator     */
  192.                                        /* display                    */
  193.               WinSetWindowText(WinWindowFromID(hwnd, DISPLAY),
  194.                   display);
  195.               return FALSE;            /* All done                   */
  196.  
  197.             /* The arithmetic operation keys all have a deferred     */
  198.             /* execution.  When one of these is pressed, the previous*/
  199.             /* arithmetic operation is processed using the           */
  200.             /* accumulator and the current display.  The new operator*/
  201.             /* is saved for later execution.  If no operator exists, */
  202.             /* then the current display is moved to the accumulator  */
  203.             /* and no arithmetic is done                             */
  204.  
  205.             case BUTTON_MULTIPLY:      /* Multiply key               */
  206.             case BUTTON_DIVIDE:        /* Division key               */
  207.             case BUTTON_PLUS:          /* Addition key               */
  208.             case BUTTON_MINUS:         /* Subtraction key            */
  209.             case BUTTON_ENTER:         /* "Total" key                */
  210.  
  211.                                        /* Process pending operations */
  212.               ProcessArithmetic(action);
  213.               SetDisplay(accumulator); /* set the new display value  */
  214.                                        /* update the calculator      */
  215.                                        /* display                    */
  216.               WinSetWindowText(WinWindowFromID(hwnd, DISPLAY),
  217.                   display);
  218.               return FALSE;            /* All done                   */
  219.  
  220.             default:                   /* Unknown, can't handle this */
  221.                return FALSE;
  222.          }
  223.  
  224.       case WM_ERASEBACKGROUND:         /* disable background erase   */
  225.         return MRFROMLONG(TRUE);       /* don't allow this           */
  226.  
  227.       /* Message not handled by us.  PM gives us first chance at all */
  228.       /* messages.  Those we don't want to process we pass on to the */
  229.       /* default dialog procedure.                                   */
  230.  
  231.       default:
  232.          return WinDefWindowProc(hwnd, msg, mp1, mp2);
  233.  
  234.    }
  235.  
  236.    return FALSE;                       /* Should never reach here    */
  237.  }
  238.  
  239. /*********************************************************************/
  240. /*                                                                   */
  241. /* AddDigit(digit) - add a digit to the calculator display           */
  242. /*                                                                   */
  243. /*********************************************************************/
  244.  
  245. VOID AddDigit(
  246. INT    digit )                         /* new digit to add           */
  247. {
  248.  
  249.   digit += (INT)'0';                   /* convert to character value */
  250.  
  251.   if (digits < MAX_DIGITS) {           /* if small enough            */
  252.      display[digits++] = (UCHAR)digit; /* add new digit to display   */
  253.      display[digits] = '\0';           /* add new string terminator  */
  254.   }
  255. }
  256.  
  257. /*********************************************************************/
  258. /*                                                                   */
  259. /* GetDisplay() - Convert current display value into a binary long   */
  260. /*                integer in the variable operand                    */
  261. /*                                                                   */
  262. /*********************************************************************/
  263.  
  264. INT  GetDisplay(void)
  265. {
  266.  
  267.    if (!digits)                        /* if nothing entered         */
  268.      operand = 0L;                     /* just use zero              */
  269.    else {
  270.      digits = 0;                       /* we've used this value      */
  271.      operand = atoi(display);          /* convert the display value  */
  272.    }
  273.    return operand;                     /* return the value           */
  274. }
  275.  
  276. /*********************************************************************/
  277. /*                                                                   */
  278. /* SetDisplay(newdisplay) - Set the current display string to a new  */
  279. /*                display value.                                     */
  280. /*                                                                   */
  281. /*********************************************************************/
  282.  
  283. VOID SetDisplay(
  284. LONG  newdisplay )                     /* new number to display      */
  285. {
  286.    sprintf(display,"%ld",newdisplay);  /* just use sprintf to update */
  287.  
  288. }
  289.  
  290. /*********************************************************************/
  291. /*                                                                   */
  292. /* ProcessArithmetic(newaction)  -  Process any pending arithmetic   */
  293. /*                operation updating the accumulator and the pending */
  294. /*                operation.                                         */
  295. /*                                                                   */
  296. /*********************************************************************/
  297.  
  298. VOID ProcessArithmetic(
  299.   LONG  newaction )                    /* new operator key pressed   */
  300. {
  301.  
  302.    switch(oldaction) {                 /* process prior action key   */
  303.  
  304.      case BUTTON_MULTIPLY:             /* multiplication             */
  305.  
  306.        accumulator *= GetDisplay();    /* multiplay accumulator by   */
  307.                                        /* current display            */
  308.        break;                          /* no more needed             */
  309.  
  310.      case BUTTON_DIVIDE:               /* division                   */
  311.  
  312.        accumulator /= GetDisplay();    /* divide accumulator by      */
  313.                                        /* current display            */
  314.        break;                          /* no more needed             */
  315.  
  316.      case BUTTON_PLUS:                 /* addition                   */
  317.  
  318.        accumulator += GetDisplay();    /* add accumulator to         */
  319.                                        /* current display            */
  320.        break;                          /* no more needed             */
  321.  
  322.      case BUTTON_MINUS:                /* subtraction                */
  323.  
  324.        accumulator -= GetDisplay();    /* subtract current display   */
  325.                                        /* from accumulator           */
  326.        break;                          /* no more needed             */
  327.  
  328.      case BUTTON_ENTER:                /* enter key                  */
  329.  
  330.        break;                          /* ignore old action          */
  331.  
  332.      default:
  333.        accumulator = GetDisplay();     /* just move display into the */
  334.                                        /* accumulator                */
  335.        break;                          /* no more needed             */
  336.  
  337.    }
  338.    oldaction = newaction;              /* remember the new action    */
  339. }
  340.